/*
 * @(#)ComponentTypeMapper.java   09/09/13
 *
 * Copyright (C) 2009 Ecole des Mines d'Ales
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Contact: yulinz88@gmail.com
 *
 *
 *
 */



package fr.ema.arch3d.ADL.specification.componentType;

import fr.ema.arch3d.ref.Fractal;
import fr.ema.arch3d.model.architecture.ComponentType;

import org.objectweb.fractal.api.NoSuchInterfaceException;
import org.objectweb.fractal.api.factory.InstantiationException;
import org.objectweb.fractal.api.type.InterfaceType;
import org.objectweb.fractal.api.type.TypeFactory;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

import java.io.CharArrayWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

/**
 * Class description
 *
 *
 * @version        1.0, 09/09/13
 * @author         Huaxi (Yulin) ZHANG
 */
public class ComponentTypeMapper extends DefaultHandler {

    // store the interface information

    /** Field description */
    private Object[] i = new Object[5];

    // Buffer for collecting data from
    // the "characters" SAX event.

    /** Field description */
    private CharArrayWriter contents = new CharArrayWriter();

    /** Field description */
    private ComponentType ct;

    /** Field description */
    DefinitionCmpTypeHandler defHandler;

    /** Field description */
    private InterfaceType itf;

    // Parent...

    /** Field description */
    ContentHandler parent;

    // XML Parser

    /** Field description */
    XMLReader parser;

    /**
     * Constructs ...
     *
     *
     * @param parser
     * @param parent
     * @param ct
     */
    public ComponentTypeMapper(XMLReader parser, ContentHandler parent, ComponentType ct) {
        this.parent = parent;
        this.parser = parser;
        parser.setContentHandler(this);
        this.ct = ct;
    }

    public void startElement(String namespaceURI, String localName, String qName, Attributes attr) throws SAXException {
        contents.reset();

        if (localName.equals("component-type")) {
            ct.name = attr.getValue("name");
        }

        if (localName.equals("def-component-type")) {
            try {
                String file = attr.getValue("name");

                file = file.replace(".", "//");
                file = "src//main//java//example//componentTypes//" + file + ".xml";

                // String file="src//example//cd.xml";
                // Create SAX 2 parser...
                XMLReader xr = XMLReaderFactory.createXMLReader();

                // Set the ContentHandler...
                DefinitionCmpTypeHandler defHandler = new DefinitionCmpTypeHandler(xr, ct);

                xr.setContentHandler(defHandler);

                // Parse the file...
                xr.parse(new InputSource(new FileReader(file)));

                // System.out.println(defHandler.ct.name);
            } catch (FileNotFoundException e) {

                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {

                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        if (localName.equals("interface")) {

            // name
            i[0] = attr.getValue("name");

            // System.out.println("rrrrrrr"+attr.getValue("name"));
            // get role description
            if (attr.getValue("role").equals("client")) {
                i[1] = "true";
            } else if (attr.getValue("role").equals("server")) {
                i[1] = "false";
            }

            // get signature description
            i[2] = attr.getValue("signature");

            if (attr.getLength() == 4) {

                // get contingency description
                if (attr.getValue("contingency").equals("mandatory")) {
                    i[3] = "false";
                } else if (attr.getValue("contingency").equals("optional")) {
                    i[3] = "true";
                }
            }

            if (attr.getLength() == 5) {

                // get cardinality description
                if (attr.getValue("cardinality").equals("singleton")) {
                    i[4] = "false";
                } else if (attr.getValue("cardinality").equals("collection")) {
                    i[4] = "true";
                }
            }
        }
    }

    // Override methods of the DefaultHandler class
    // to gain notification of SAX Events.
    //
    // See org.xml.sax.ContentHandler for all available events.
    //
    public void endElement(String namespaceURI, String localName, String qName) throws SAXException {

        // System.out.println("componentMapper="+localName);

        /*
         * if ( localName.equals( "definition" ) ) {
         *       System.out.println("here");
         *
         *       // Create SAX 2 parser...
         *       XMLReader xr = XMLReaderFactory.createXMLReader();
         *
         *       // Set the ContentHandler...
         *       DefinitionHandler defHandler = new DefinitionHandler(xr);
         *       xr.setContentHandler(defHandler);
         *
         *       // Parse the file...
         *       xr.parse( new InputSource(
         *                       new FileReader(file)) );
         *
         * }
         */

        // define interface
        if (localName.equals("interface")) {

            // System.out.println("here");
            org.objectweb.fractal.api.Component boot;

            System.setProperty("fractal.provider", "org.objectweb.fractal.julia.Julia");
            System.setProperty("julia.config", "julia-bundled.cfg");

            // JULIA_LOADER
            System.setProperty("julia.loader", "org.objectweb.fractal.julia.loader.DynamicLoader");    // //////

            try {
                boot = Fractal.getBootstrapComponent();

                try {
                    TypeFactory tf = Fractal.getTypeFactory(boot);

                    itf = (InterfaceType) tf.createFcItfType((String) i[0], (String) i[2],
                            (Boolean.getBoolean((String) i[2])), (Boolean.getBoolean((String) i[3])),
                            (Boolean.getBoolean((String) i[4])));
                    ct.interfaceType_list.add(itf);
                } catch (NoSuchInterfaceException e) {

                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } catch (InstantiationException e) {

                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        if (localName.equals("component-type")) {

            // swap content handler back to parent
            parser.setContentHandler(parent);
        }
    }

    public void characters(char[] ch, int start, int length) throws SAXException {

        // accumulate the contents into a buffer.
        contents.write(ch, start, length);
    }
}
